#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Base Connector Class for Trading Bot

This module defines the base connector class that replaces
Hummingbot's ExchangeBase for our lightweight framework.
"""

import asyncio
import time
from abc import ABC, abstractmethod
from decimal import Decimal
from typing import Dict, List, Optional, Any
from enum import Enum


class NetworkStatus(Enum):
    """Network connection status"""
    CONNECTED = "connected"
    NOT_CONNECTED = "not_connected"
    STOPPED = "stopped"


class TokenAmount:
    """Token amount representation"""
    
    def __init__(self, token: str, amount: Decimal):
        self.token = token
        self.amount = amount


class TradeFeeBase:
    """Trade fee base class"""
    
    def __init__(self, fee_asset: str, flat_fees: List[TokenAmount] = None, percent: Decimal = Decimal("0")):
        self.fee_asset = fee_asset
        self.flat_fees = flat_fees or []
        self.percent = percent


class TradingRule:
    """Trading rule for a trading pair"""
    
    def __init__(self,
                 trading_pair: str,
                 min_order_size: Decimal,
                 max_order_size: Decimal,
                 min_price_increment: Decimal,
                 min_base_amount_increment: Decimal,
                 min_quote_amount_increment: Decimal = None):
        self.trading_pair = trading_pair
        self.min_order_size = min_order_size
        self.max_order_size = max_order_size
        self.min_price_increment = min_price_increment
        self.min_base_amount_increment = min_base_amount_increment
        self.min_quote_amount_increment = min_quote_amount_increment or min_price_increment


class InFlightOrder:
    """In-flight order representation"""
    
    def __init__(self,
                 client_order_id: str,
                 exchange_order_id: Optional[str],
                 trading_pair: str,
                 order_type: 'OrderType',
                 trade_type: 'TradeType',
                 amount: Decimal,
                 price: Decimal,
                 creation_timestamp: Optional[int] = None):
        self.client_order_id = client_order_id
        self.exchange_order_id = exchange_order_id
        self.trading_pair = trading_pair
        self.order_type = order_type
        self.trade_type = trade_type
        self.amount = amount
        self.price = price
        self.creation_timestamp = creation_timestamp or int(time.time() * 1000)
        self.executed_amount_base = Decimal("0")
        self.executed_amount_quote = Decimal("0")
        self.fee_asset = ""
        self.fee_paid = Decimal("0")
        self.last_state = "open"


class ConnectorBase(ABC):
    """Base class for exchange connectors"""
    
    def __init__(self, trading_pairs: List[str]):
        self._trading_pairs = trading_pairs
        self._trading_rules: Dict[str, TradingRule] = {}
        self._in_flight_orders: Dict[str, InFlightOrder] = {}
        self._account_balances: Dict[str, Decimal] = {}
        self._network_status = NetworkStatus.NOT_CONNECTED
        self._last_timestamp = 0
        self._ready = False
    
    @property
    def trading_pairs(self) -> List[str]:
        return self._trading_pairs
    
    @property
    def trading_rules(self) -> Dict[str, TradingRule]:
        return self._trading_rules
    
    @property
    def in_flight_orders(self) -> Dict[str, InFlightOrder]:
        return self._in_flight_orders
    
    @property
    def account_balances(self) -> Dict[str, Decimal]:
        return self._account_balances
    
    @property
    def network_status(self) -> NetworkStatus:
        return self._network_status
    
    @property
    def ready(self) -> bool:
        return self._ready
    
    @property
    def current_timestamp(self) -> int:
        return int(time.time() * 1000)
    
    def get_balance(self, currency: str) -> Decimal:
        """Get balance for a specific currency"""
        return self._account_balances.get(currency, Decimal("0"))
    
    def get_price(self, trading_pair: str) -> Decimal:
        """Get current price for a trading pair"""
        # This should be implemented by subclasses
        return Decimal("0")
    
    @abstractmethod
    async def start_network(self):
        """Start network connections"""
        pass
    
    @abstractmethod
    async def stop_network(self):
        """Stop network connections"""
        pass
    
    @abstractmethod
    async def check_network_status(self) -> NetworkStatus:
        """Check network connection status"""
        pass
    
    @abstractmethod
    async def update_trading_rules(self):
        """Update trading rules from exchange"""
        pass
    
    @abstractmethod
    async def update_balances(self):
        """Update account balances"""
        pass
    
    @abstractmethod
    async def place_order(self,
                         order_id: str,
                         trading_pair: str,
                         amount: Decimal,
                         order_type: 'OrderType',
                         is_buy: bool,
                         price: Decimal = None) -> str:
        """Place an order"""
        pass
    
    @abstractmethod
    async def cancel_order(self, order_id: str) -> bool:
        """Cancel an order"""
        pass
    
    @abstractmethod
    async def get_order_status(self, order_id: str) -> Dict[str, Any]:
        """Get order status"""
        pass
    
    async def start(self):
        """Start the connector"""
        await self.start_network()
        await self.update_trading_rules()
        await self.update_balances()
        self._ready = True
    
    async def stop(self):
        """Stop the connector"""
        await self.stop_network()
        self._ready = False